{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 为什么NumPy数组结构比Python本身的列表list好？\n",
    "\n",
    "- list元素在系统内存中是分散的，NumPy数组存储在均匀连续的内存块中，查找的时候不需要想list那样对内存地址进行查找，节省计算资源\n",
    "- 在内存访问模式中，缓存会直接把字节块从RAM加载到CPU寄存器中\n",
    "- NumPy中的矩阵计算可采用多线程的方式，提高效率\n",
    "- NumPy避免采用隐式拷贝，而采用就地操作的方式，例如x\\*=2比y=x\\*2速度快两倍\n",
    "\n",
    "ndarray对象创建数组，又如何处理结构数组？？"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "a = np.array([1,2,3])\n",
    "b = np.array([[1,2,3],[4,5,6],[7,8,9]])\n",
    "b[1,1] = 10\n",
    "print(a.shape)\n",
    "print(b.shape)\n",
    "print(a.dtype)\n",
    "print(b)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "统计一个班级里面学生的姓名、年龄，以及语文、英语、数学成绩该怎么办？"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "# 用dtype定义结构类型\n",
    "persontype = np.dtype({\n",
    "    'names':['name', 'age', 'chinese', 'math', 'english'],\n",
    "    'formats':['S32','i', 'i', 'i', 'f']})\n",
    "# 用array指定结构数组的类型 dtype = persontype\n",
    "peoples = np.array([(\"ZhangFei\",32,75,100, 90),(\"GuanYu\",24,85,96,88.5),\n",
    "       (\"ZhaoYun\",28,85,92,96.5),(\"HuangZhong\",29,65,85,100)],\n",
    "    dtype=persontype)\n",
    "ages = peoples[:]['age']\n",
    "chineses = peoples[:]['chinese']    # 计算每个人的语文成绩\n",
    "maths = peoples[:]['math']\n",
    "englishs = peoples[:]['english']\n",
    "\n",
    "print (np.mean(ages))    # np.mean计算平均值\n",
    "print (np.mean(chineses))\n",
    "print (np.mean(maths))\n",
    "print (np.mean(englishs))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "NumPy 可以很方便地创建连续数组，比如我使用 arange 或 linspace 函数进行创建：\n",
    "\n",
    "np.arange 和 np.linspace 起到的作用是一样的，都是创建等差数组。\n",
    "\n",
    "arange() 类似内置函数 range()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "x1 = np.arange(1,11,2)\n",
    "x2 = np.linspace(1,9,5)\n",
    "print(\"x1=\", x1, \"\\nx2=\", x2)\n",
    "print (\"对应值相加：\",np.add(x1, x2))\n",
    "print (\"对应值相减：\",np.subtract(x1, x2))\n",
    "print (\"对应值相成：\",np.multiply(x1, x2))\n",
    "print (\"对应值相除：\",np.divide(x1, x2))\n",
    "print (\"求 n 次方：\",np.power(x1, x2))\n",
    "print (\"取余数：\",np.remainder(x1, x2)) # 可以用 np.mod(x1, x2)，结果是一样的。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "NumPy 中如何使用统计函数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "a = np.array([[1,2,3], [4,5,6], [7,8,9]])\n",
    "print (np.amin(a))  # 数组中全部元素最小值\n",
    "print (np.amin(a,0))  # 延着axis=0轴的最小值；axis=0轴是把元素看成了[1,4,7],[2,5,8],[3,6,9] 三个元素\n",
    "print (np.amin(a,1))  # amin(a,1)是延着axis=1轴的最小值，axis=1轴是把元素看成了[1,2,3],[4,5,6],[7,8,9] 三个元素\n",
    "print (np.amax(a))  # 同理\n",
    "print (np.amax(a,0))\n",
    "print (np.amax(a,1))\n",
    "\n",
    "# 统计最大值和最小值之差ptp()\n",
    "print (np.ptp(a))\n",
    "print (np.ptp(a,0))\n",
    "print (np.ptp(a,1))\n",
    "\n",
    "# 统计数组的百分位数percentile()\n",
    "# 注解：percentile() 代表着第 p 个百分位数，这里 p的取值范围是 0-100，\n",
    "# 如果 p=0，那么就是求最小值，如果 p=50 就是求平均值，如果 p=100 就是求最大值。\n",
    "# 同样你也可以求得在 axis=0 和 axis=1 两个轴上的 p% 的百分位数。\n",
    "print (np.percentile(a, 50))\n",
    "print (np.percentile(a, 50, axis=0))\n",
    "print (np.percentile(a, 50, axis=1))\n",
    "\n",
    "# 统计数组中的中位数 median()、平均数 mean()\n",
    "# 求中位数\n",
    "print (np.median(a))\n",
    "print (np.median(a, axis=0))\n",
    "print (np.median(a, axis=1))\n",
    "# 求平均数\n",
    "print (np.mean(a))\n",
    "print (np.mean(a, axis=0))\n",
    "print (np.mean(a, axis=1))\n",
    "\n",
    "# 统计数组中的加权平均值 average()\n",
    "# 加权平均的意思就是每个元素可以设置个权重，默认情况下每个元素的权重是相同的\n",
    "# np.average(a)=(1+2+3+4)/4=2.5，也可以指定权重数组 wts=[1,2,3,4]，这样加权平均 np.average(a,weights=wts)=(1*1+2*2+3*3+4*4)/(1+2+3+4)=3.0。\n",
    "a = np.array([1,2,3,4])\n",
    "wts = np.array([1,2,3,4])\n",
    "print (np.average(a))\n",
    "print (np.average(a,weights=wts))\n",
    "\n",
    "# 统计数组中的标准差 std()、方差 var()\n",
    "# 方差的计算是指每个数值与平均值之差的平方求和的平均值\n",
    "# 标准差是方差的算术平方根。在数学意义上，代表的是一组数据离平均值的分散程度。\n",
    "a = np.array([1,2,3,4])\n",
    "print (np.std(a))\n",
    "print (np.var(a))\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "NumPy 排序：\n",
    "\n",
    "排序算法在 NumPy 中实现很简单。使用 sort 函数，sort(a, axis=-1, kind=‘quicksort’, order=None)，默认情况下使用的是快速排序；在 kind 里，可以指定 quicksort、mergesort、heapsort 分别表示快速排序、合并排序、堆排序。同样 axis 默认是 -1，即沿着数组的最后一个轴进行排序，也可以取不同的 axis 轴，或者 axis=None 代表采用扁平化的方式作为一个向量进行排序。另外 order 字段，对于结构化的数组可以指定按照某个字段进行排序。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "a = np.array([[4,3,2],[2,4,1]])\n",
    "print (np.sort(a))\n",
    "print (np.sort(a, axis=None))\n",
    "print (np.sort(a, axis=0))\n",
    "print (np.sort(a, axis=1)) "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "总结：\n",
    "\n",
    "NumPy重点学习对数组的使用，因为这是 NumPy 和标准 Python 最大的区别"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "练习题：统计全班的成绩\n",
    "\n",
    "假设一个团队里有 5 名学员，成绩如下表所示。你可以用 NumPy 统计下这些人在语文、英语、数学中的平均成绩、最小成绩、最大成绩、方差、标准差。然后把这些人的总成绩排序，得出名次进行成绩输出。\n",
    "\n",
    "姓名   语   英   数\n",
    "\n",
    "name1  66  65   30\n",
    "\n",
    "name2  95  85   98\n",
    "\n",
    "name3  93  92   96\n",
    "\n",
    "name4  90  88   77\n",
    "\n",
    "name5  80  90   90"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "# studentType = np.dtype({\n",
    "#     'names':['语文','英语','数学'],\n",
    "#     'formats':['S32','i','i','i']\n",
    "# })\n",
    "# students = np.array(\n",
    "#     [[\"name\",66,65,30],[\"name2\",95,85,98],[\"name3\",93,92,96],[\"name4\",90,88,77],[\"name5\",80,90,90]],\n",
    "#     dtype = studentType\n",
    "# )\n",
    "students = np.array([[66,65,30],[95,85,98],[93,92,96],[90,88,77],[80,90,90]])\n",
    "print (\"name1/2/3/4/5的平均成绩：\",np.mean(students,axis=1))\n",
    "print (\"name1/2/3/4/5的最小成绩：\",np.amin(students,axis=1))\n",
    "print (\"name1/2/3/4/5的最大成绩：\",np.amax(students,axis=1))\n",
    "print (\"name1/2/3/4/5的方差：\",np.var(students,axis=1))\n",
    "print (\"name1/2/3/4/5的标准差：\",np.std(students,axis=1))\n",
    "print (\"name1/2/3/4/5的总成绩：\",np.sum(students,axis=1))\n",
    "print (\"name的总成绩排序：\",np.sort(np.sum(students,axis=1)))"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
